/***** JFlex specification for Common Lisp *****/

package com.bitbakery.plugin.lisp.lang.lexer;

import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import static com.bitbakery.plugin.lisp.lang.lexer.LispTokenTypes.*;
import java.util.*;
import java.lang.reflect.Field;
import org.jetbrains.annotations.NotNull;

%%

%class _LispLexer
%implements FlexLexer
%unicode
%public

%function advance
%type IElementType



/***** Custom user code *****/

%{
    StringBuffer string = new StringBuffer();
%}




/***** Macros - Regular expressions *****/

LineTerminator=\r|\n|\r\n
InputCharacter=[^\r\n]
WhiteSpace={LineTerminator}|[ \t\f]

LineComment=([ \t\f]*";"{InputCharacter}*{LineTerminator})


COMMENT_TAIL=([^"*"]*("*"+[^"*""/"])?)*("*"+"/")?

BlockComment=(("#\|")(.*)("\|#"))

/*****  BlockComment=([ \t\f]*"#\|".*"\|#") ******/

Digit=[0-9]
IntegerLiteral=(0|([1-9]({Digit})*))

ExponentPart=[Ee]["+""-"]?({Digit})*
FloatingPointLiteral1=({Digit})+"."({Digit})*({ExponentPart})?
FloatingPointLiteral2="."({Digit})+({ExponentPart})?
FloatingPointLiteral3=({Digit})+({ExponentPart})
FloatingPointLiteral4=({Digit})+
FloatLiteral=({FloatingPointLiteral1})|({FloatingPointLiteral2})|({FloatingPointLiteral3})|({FloatingPointLiteral4})

NumericLiteral=["+""-"]?({IntegerLiteral})|({FloatLiteral})

/**** TODO - Include support for pipe-delimited symbols **************/
Symbol=[A-Za-z0-9!@#$%<>/?&\^\+\*\-=\.\?:]*

EscapeSequence=\\[^\r\n]
StringLiteral=\"([^\\\"]|{EscapeSequence})*(\"|\\)?


%%

{WhiteSpace}    { return WHITESPACE; }
{LineComment}   { return LINE_COMMENT; }
{BlockComment}  { return BLOCK_COMMENT; }
{NumericLiteral} { return NUMERIC_LITERAL; }
{StringLiteral} { return STRING_LITERAL; }


/** TODO - Any other tokens? Exception stuff? Other keyword-style, commonly used macros? *******************/

"("             { return LEFT_PAREN; }
")"             { return RIGHT_PAREN; }

[Tt]            { return TRUE; }
[Nn][Ii][Ll]    { return NIL; }

[Qq][Uu][Oo][Tt][Ee]        { return QUOTE_KEYWORD; }
[Ll][Aa][Mm][Bb][Dd][Aa]    { return LAMBDA; }
[Cc][Oo][Nn][Dd]            { return COND; }
[Ii][Ff]                    { return IF; }
[Ll][Ee][Tt]                { return LET; }
[Ww][Hh][Ee][Nn]            { return WHEN; }
[Uu][Nn][Ll][Ee][Ss][Ss]    { return UNLESS; }
[Pp][Rr][Oo][Gg][Nn]        { return PROGN; }
[Ss][Ee][Tt][Qq]            { return SETQ; }

"`"             { return BACKQUOTE; }
"'"             { return QUOTE; }
","             { return COMMA; }
",@"            { return COMMA_AT; }
"#'"            { return SHARP_QUOTE; }

[Dd][Ee][Ff][Uu][Nn]                { return DEFUN; }
[Dd][Ee][Ff][Mm][Aa][Cc][Rr][Oo]    { return DEFMACRO; }
[Dd][Ee][Ff][Vv][Aa][Rr]            { return DEFVAR; }
[Dd][Ee][Ff][Cc][Ll][Aa][Ss][Ss]        { return DEFCLASS; }
[Dd][Ee][Ff][Mm][Ee][Tt][Hh][Oo][Dd]    { return DEFMETHOD; }
[Dd][Ee][Ff][Gg][Ee][Nn][Ee][Rr][Ii][Cc]    { return DEFGENERIC; }
[Dd][Ee][Ff][Pp][Aa][Cc][Kk][Aa][Gg][Ee]    { return DEFPACKAGE; }
[Dd][Ee][Ff][Pp][Aa][Rr][Aa][Mm][Ee][Tt][Ee][Rr]    { return DEFPARAMETER; }
[Dd][Ee][Ff][Cc][Oo][Nn][Ss][Tt][Aa][Nn][Tt]        { return DEFCONSTANT; }

"&"[Aa][Uu][Xx]                     { return AUX; }
"&"[Bb][Oo][Dd][Yy]                 { return BODY; }
"&"[Kk][Ee][Yy]                     { return KEY; }
"&"[Oo][Pp][Tt][Ii][Oo][Nn][Aa][Ll] { return OPTIONAL; }
"&"[Rr][Ee][Ss][Tt]                 { return REST; }

{Symbol}        { return SYMBOL; }

.               { return BAD_CHARACTER; }